package net.sochk.web.impl;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Repository;
import org.springframework.web.multipart.MultipartFile;

import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.Expand;
import net.sochk.web.dao.ZipDecompressionToWebLocationDao;
import com.github.junrar.Archive;
import com.github.junrar.exception.RarException;
import com.github.junrar.rarfile.FileHeader;



public class ZipDecompressionToWebLocation implements ZipDecompressionToWebLocationDao {

	private final String yumingPath = "http://localhost:8080";
	private final String xiangmumingPath = "webapp";
	
	/**
	 * ���ļ���ѹ������ǰĿ¼����ѹ���ļ�ɾ��
	 */
	public String decompressionToWebLocation(MultipartFile zip, HttpServletRequest request) {
		String fileName = zip.getOriginalFilename();
		String fileType = fileName.substring(fileName.lastIndexOf(".")+1,fileName.length());
		// �ж��ļ��Ƿ�Ϊzip��ʽ��rar��ʽ
		if(!fileType.equals("zip")&&!fileType.equals("rar")){
			return "faultType";
		}
		
		String realPath = request.getSession().getServletContext().getRealPath("/");
		System.out.println(realPath+"789456123");
		// �ϴ��ļ�������, �������ļ�·��(�����ļ���)
		String sourceZip = uploadZipToWebLocation(zip, realPath);
		// �ϴ��ɹ�����н�ѹ, ��ɾ��ԭѹ���ļ�
		if(sourceZip!=null){
			if(fileType.equals("zip")){
				if(!decompressZip(sourceZip, realPath)){
					deleteZip(sourceZip);
					return "failDecompress";
				}
			}else{
				if(!decompressRar(sourceZip, realPath)){
					deleteZip(sourceZip);
					return "failDecompress";
				}
			}
		}
		deleteZip(sourceZip);
		
		// the file have been decompressed
		File src = new File(realPath + getSrc(fileName));
		
		//return renameSrc(src);
		return src.getName();
	}
	
	/**
	 * �����ļ������Ŀ¼��
	 * @param fileName
	 * @return
	 */
	private String getSrc(String fileName) {
		String src = fileName.substring(0, fileName.lastIndexOf("."));
		return src;
	}

	/**
	 * ��ѹ�������浽web·���£����ɹ��򷵻��ļ���·��
	 * @param zip
	 * @param realPath
	 * @return
	 */
	public String uploadZipToWebLocation(MultipartFile zip, String realPath){
		realPath = realPath + zip.getOriginalFilename();
		System.out.println(realPath);
		File file = new File(realPath);
		System.out.println(file);
		try {
			BufferedInputStream bufIn = new BufferedInputStream(zip.getInputStream());
			FileOutputStream out = new FileOutputStream(file);
			BufferedOutputStream bufOut = new BufferedOutputStream(out);
			int len;
			byte[] bys = new byte[1024];
			while((len=bufIn.read(bys))!=-1){
				bufOut.write(bys, 0, len);
			}
			bufOut.close();
			bufIn.close();
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
		
		return realPath;
	}
	
	/**
	 * ��zip�ļ���ѹ��ָ��Ŀ¼
	 * @param sourceZip			�ļ�·��(�����ļ���)
	 * @param decompressionDir	��ѹ�� Ŀ�� Ŀ¼
	 * @return
	 */
	public boolean decompressZip(String sourceZip, String decompressionDir){
		try {
			Project project = new Project();
			Expand expand = new Expand();
			expand.setProject(project);
			expand.setSrc(new File(sourceZip));
			expand.setOverwrite(false);
			expand.setDest(new File(decompressionDir));
			
			expand.setEncoding("gbk");
			expand.execute();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		}
		
		return true;
	}
	
	/**
	 * ��ѹrar��ʽ��ѹ����
	 * @param sourceRar		�ļ�·���������ļ���
	 * @param destDir		��ѹ��Ŀ��Ŀ¼
	 * @return
	 */
	public boolean decompressRar(String sourceRar, String destDir){
		boolean uploadStatus = true;
		
		Archive archive = null;
		FileOutputStream fos = null;
		
		try {
			archive = new Archive(new File(sourceRar));
			FileHeader  fileHeader = archive.nextFileHeader();
			while(fileHeader!=null){
				if(!fileHeader.isDirectory()){
					String decompressFileName = fileHeader.getFileNameString();
					String destFileName = "";
					String destDirName = "";
					// ��Windowsϵͳ
					if(File.separator.equals("/")){
						destFileName = destDir + decompressFileName.replaceAll("\\\\", "/");
						destDirName = destFileName.substring(0, destFileName.lastIndexOf("/"));
					// Windowsϵͳ
					}else{
						destFileName = destDir + decompressFileName.replaceAll("/", "\\");
						destDirName = destFileName.substring(0, destFileName.lastIndexOf("\\"));
					}
					
					// �����ļ���
					File dir = new File(destDirName);
					if(!dir.exists() || !dir.isDirectory()){
						dir.mkdirs();
					}
					fos = new FileOutputStream(new File(destFileName));
					archive.extractFile(fileHeader, fos);
					fos.close();
					fos = null;
					
				}
				fileHeader= archive.nextFileHeader();
			}
			archive.close();
			archive = null;
		} catch (Exception e) {
			e.printStackTrace();
			uploadStatus=false;
		} finally{
			if(fos != null){
				try {
					fos.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			if(archive != null){
				try {
					archive.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		
		return uploadStatus;
	}
	
	/**
	 * ��ָ��·����ѹ���ļ�ɾ��
	 * @param zipPath
	 * @return
	 */
	public boolean deleteZip(String zipPath){
		File file = new File(zipPath);
		file.delete();
		return false;
	}
	
	/**
	 * rename a src to a new name with the time stamp.
	 * @param src that should be renamed.
	 * @return  if success, return new name, 
	 * 			else, return old name.
	 */
	public String renameSrc(File src){
		// generate new name of the file
		Date date = new Date();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
		String timeStamp = sdf.format(date);
		String newName = src.getAbsolutePath() + timeStamp;
		
		// rename src
		if(src.renameTo(new File(newName)))
			return src.getName() + timeStamp;
		else
			return src.getName();
	}

}
